//****************************************************************************      
// @Filename      CAN.c
//****************************************************************************
#include "stm32f4xx_gpio.h"
#include "stm32f4xx_can.h"
#include "stm32f4xx_rcc.h"
#include "typedefs.h"
#include "CAN.h"
#include "flash.h"
#include "mainInclude.h"

//----------------------------------------------------------------------------
uint16_t       MCU_RX=0,MCU_TX=0; 
uint8_t        gCanMCURXG0[8]={0};
uint16_t       gCanMCURXOkFlagG0=0;

//****************************************************************************
// @Prototypes Of Local Functions
//****************************************************************************
void CAN_BusoffError(void);
void InitCAN(void);
void CAN_CfgDebugMail(void);
void CpCoreBaudrate(int16 ubBaudSelV);
extern void   CAN_Cfg1939Mail(void);

//****************************************************************************
// @Function      void CAN_vInit(void) 
//
//----------------------------------------------------------------------------
// @Description   This is the initialization function of the CAN function 
//                library. It is assumed that the SFRs used by this library 
//                are in their reset state. 
//
//----------------------------------------------------------------------------
//****************************************************************************
void CAN_vInit(uint32 CanBaudRate)
{		
	GPIO_InitTypeDef       GPIO_InitStructure;
	CAN_InitTypeDef 	   CAN_InitStructure;
	CAN_FilterInitTypeDef  CAN_FilterInitStructure;
	Uint32                 wTemp=0;

	GPIO_StructInit(&GPIO_InitStructure);
	CAN_StructInit(&CAN_InitStructure);

	RCC_AHB1PeriphClockCmd(CAN1_GPIO_RCC_Periph, ENABLE); 	
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);

	GPIO_PinAFConfig(CAN1_GPIO,  CAN1_GPIO_Source_RX,   GPIO_AF_CAN1);
	GPIO_PinAFConfig(CAN1_GPIO,  CAN1_GPIO_Source_TX,   GPIO_AF_CAN1);

	GPIO_InitStructure.GPIO_Pin = CAN1_GPIO_PIN_RX| CAN1_GPIO_PIN_TX;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
    GPIO_Init(CAN1_GPIO, &GPIO_InitStructure);

	RCC_AHB1PeriphClockCmd(CAN1_GPIO_EN_RCC, ENABLE);
	GPIO_InitStructure.GPIO_Pin = CAN1_GPIO_PIN_EN; 		 
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_25MHz;
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
	GPIO_Init(CAN1_GPIO_EN, &GPIO_InitStructure);
	CAN1_EN;

	MCU_RX = DevInfoCur.ServoID&0xffff;
	MCU_TX = (DevInfoCur.ServoID + 0x100)&0xffff;
	
	CAN_DeInit(CAN1);
	CAN_StructInit(&CAN_InitStructure);

	/* CAN cell init */
	CAN1->MCR &=0xFFFEFFFF; 
	//时间触发模式
	CAN_InitStructure.CAN_TTCM=DISABLE;
	//自动离线管理
    CAN_InitStructure.CAN_ABOM=ENABLE;
	//自动唤醒模式
    CAN_InitStructure.CAN_AWUM=ENABLE;
	//报文自动重传
    CAN_InitStructure.CAN_NART=DISABLE;
	//FIFO溢出时报文覆盖源文件
    CAN_InitStructure.CAN_RFLM=DISABLE;
	//报文发送优先级取决于ID号
    CAN_InitStructure.CAN_TXFP=ENABLE;
	//工作模式（正常）
	CAN_InitStructure.CAN_Mode=CAN_Mode_Normal;
	CAN_InitStructure.CAN_SJW=CAN_SJW_1tq;	
    if(250000UL == CanBaudRate)
	{ 
       CAN_InitStructure.CAN_BS1=CAN_BS1_12tq; 
	   CAN_InitStructure.CAN_BS2=CAN_BS2_2tq;
	   CAN_InitStructure.CAN_Prescaler=12;
	}
	else if(1000000UL == CanBaudRate)
	{ 
       CAN_InitStructure.CAN_BS1=CAN_BS1_12tq;
	   CAN_InitStructure.CAN_BS2=CAN_BS2_2tq;
	   CAN_InitStructure.CAN_Prescaler=3;
	}
	else  //42M / 6 / (1 + 7 +6) = 0.5M
	{ 
       CAN_InitStructure.CAN_BS1=CAN_BS1_12tq; 
	   CAN_InitStructure.CAN_BS2=CAN_BS2_2tq;
	   CAN_InitStructure.CAN_Prescaler=6;
	}
   CAN_Init(CAN1, &CAN_InitStructure);
		
   CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask;
   CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit;
   CAN_FilterInitStructure.CAN_FilterActivation=ENABLE;
   
   /* CAN filter init */ //第0组滤波，FIFO0接收数据帧  只接收标准数据帧
   CAN_FilterInitStructure.CAN_FilterNumber=0; 	
   wTemp=MCU_RX;
   CAN_FilterInitStructure.CAN_FilterIdHigh=(((u32)wTemp<<21)&0xffff0000)>>16;
   CAN_FilterInitStructure.CAN_FilterIdLow=(((u32)wTemp<<21)|CAN_ID_STD|CAN_RTR_DATA)&0xffff;
   CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0xffff;
   CAN_FilterInitStructure.CAN_FilterMaskIdLow=0xffff;
   CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_FIFO0;
   CAN_FilterInit(&CAN_FilterInitStructure);

   BusOffTime = 0;
   BusOffResetTime = 0;
}

static CanRxMsg RxMessage;
uint8_t CAN_vGetMsgObj(void)
{
	uint8_t DLC = 0;
	static Uint16 wRcvMsgNum1=0;
	static Uint16 wTemp=0;
	wRcvMsgNum1= CAN1->RF0R & CAN_RF0R_FMP0;	

	if(wRcvMsgNum1 ==0)
	{
		return 0;
	}
	
	for(wTemp=0;wTemp<wRcvMsgNum1;wTemp++)
	{
	    CAN_Receive(CAN1, CAN_FIFO0, &RxMessage);
        DLC = RxMessage.DLC;

		switch (RxMessage.FMI)
		{
			case 0:  //MCU_RX
                 gCanMCURXG0[0] = RxMessage.Data[0];
				 gCanMCURXG0[1] = RxMessage.Data[1];
				 gCanMCURXG0[2] = RxMessage.Data[2];
				 gCanMCURXG0[3] = RxMessage.Data[3];
				 gCanMCURXG0[4] = RxMessage.Data[4];
				 gCanMCURXG0[5] = RxMessage.Data[5];
				 gCanMCURXG0[6] = RxMessage.Data[6];
				 gCanMCURXG0[7] = RxMessage.Data[7];
				 gCanMCURXOkFlagG0 = 1;
				break; 
				
			default:
				
				break;
		}
	}
	
	return DLC;
}

void SendOneMessage( J1939_MESSAGE *MsgPtr,Uint16 Id)
{
    CanTxMsg TxMessage;

    TxMessage.StdId=(uint32_t)Id;
	TxMessage.IDE=CAN_ID_STD;
	TxMessage.RTR=CAN_RTR_DATA;
	TxMessage.DLC=(uint8_t)MsgPtr->FormatMsg.DataLength;
		
	TxMessage.Data[0]=(uint16_t)MsgPtr->FormatMsg.Data[0];
	TxMessage.Data[1]=(uint16_t)MsgPtr->FormatMsg.Data[0]>>8;
	TxMessage.Data[2]=(uint16_t)MsgPtr->FormatMsg.Data[1];
	TxMessage.Data[3]=(uint16_t)MsgPtr->FormatMsg.Data[1]>>8;
	TxMessage.Data[4]=(uint16_t)MsgPtr->FormatMsg.Data[2];
	TxMessage.Data[5]=(uint16_t)MsgPtr->FormatMsg.Data[2]>>8;
	TxMessage.Data[6]=(uint16_t)MsgPtr->FormatMsg.Data[3];
	TxMessage.Data[7]=(uint16_t)MsgPtr->FormatMsg.Data[3]>>8;
	CAN_Transmit(CAN1,&TxMessage);  
}

/*************************************************************************************************
 CAN busoff
 自动复位
**************************************************************************************************/
void CAN_BusoffError(void)
{
  if((CAN1->ESR & 0x00000004) == 0x00000004)	//bus off
	{
		CAN1->MCR |= 0x00008000;	  //Rst can controller
		CAN_vInit(DevInfoCur.CanBaudRate);			  //Reinitialize can controller
	}
}


